package com.yanyeori.framework.datasource.builder;

import com.yanyeori.framework.datasource.configprop.DataSourceConfigProps;
import com.yanyeori.framework.datasource.configprop.MultiDataSourceConfigProps;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

import javax.sql.DataSource;

/**
 * Hikari DataSource Builder
 *
 * @author chenkuan 2021/4/16
 */
@ConditionalOnClass(HikariDataSource.class)
public class HikariDataSourceBuilder implements DataSourceBuilder {

    @Override
    public DataSource build(DataSourceConfigProps props, MultiDataSourceConfigProps basicProps) {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setPoolName(basicProps.getName());
        dataSource.setJdbcUrl(basicProps.getUrl());
        dataSource.setUsername(basicProps.getUsername());
        dataSource.setPassword(basicProps.getPassword());
        dataSource.setDriverClassName(basicProps.getDriverClassName());
        hikariPoolConfig(dataSource, props);
        return dataSource;
    }

    @Override
    public Class<? extends DataSource> getType() {
        return HikariDataSource.class;
    }

    /**
     * Hikari连接池相关配置
     */
    private void hikariPoolConfig(HikariDataSource dataSource, DataSourceConfigProps props) {
        HikariConfigProps config = props.getHikari();
        dataSource.setMinimumIdle(config.getMinimumIdle());
        dataSource.setMaximumPoolSize(config.getMaximumPoolSize());
        dataSource.setConnectionTimeout(config.getConnectionTimeout());
        dataSource.setIdleTimeout(config.getIdleTimeout());
        dataSource.setConnectionTestQuery(config.getConnectionTestQuery());
        dataSource.setValidationTimeout(config.getValidationTimeout());
        dataSource.setCatalog(config.getCatalog());
        dataSource.setLeakDetectionThreshold(config.getLeakDetectionThreshold());
        dataSource.setMaxLifetime(config.getMaxLifetime());
        dataSource.setInitializationFailTimeout(config.getInitializationFailTimeout());
        dataSource.setConnectionInitSql(config.getConnectionInitSql());
        dataSource.setSchema(config.getSchema());
        dataSource.setTransactionIsolation(config.getTransactionIsolation());
        dataSource.setAutoCommit(config.isAutoCommit());
        dataSource.setReadOnly(config.isReadOnly());
        dataSource.setIsolateInternalQueries(config.isIsolateInternalQueries());
        dataSource.setRegisterMbeans(config.isRegisterMbeans());
        dataSource.setAllowPoolSuspension(config.isAllowPoolSuspension());
    }

    /**
     * Hikari连接池属性
     */
    @Getter
    @Setter
    public static class HikariConfigProps {
        private int minimumIdle = 1;
        private int maximumPoolSize = 10;
        private long connectionTimeout = 60 * 1000;
        private long idleTimeout = 10 * 60 * 1000;
        private String connectionTestQuery;
        private long validationTimeout = 30 * 1000;
        private String catalog;
        private long leakDetectionThreshold;
        private long maxLifetime;
        private long initializationFailTimeout;
        private String connectionInitSql;
        private String schema;
        private String transactionIsolation;
        private boolean autoCommit;
        private boolean readOnly;
        private boolean isolateInternalQueries;
        private boolean registerMbeans;
        private boolean allowPoolSuspension;
    }
}
